package com.gid.rcflightlogger;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.util.Log;

import com.gid.rcflightlogger.FlightTimerActivity.TimerState;

public class LocalTimerService extends Service {

	//Class for clients to access. Because we know this service always runs in
	//the same process as its client, we don't need to deal with IPC
	public class LocalBinder extends Binder {
		LocalTimerService getService() {
			return LocalTimerService.this;
		}
	}
	
	private static final String LOG_TAG = "LocalTimerService";
	private NotificationManager mNM;
	private PowerManager mPM;
	private WakeLock mWakeLock = null;
	
	private Handler mHandler;
	private static final int LTS_NOTIFICATION = 1; // Unique Identification Number for the notification, used to start and cancel notification
	private final IBinder mBinder = new LocalBinder();
	private FlightTimerActivity mFlightTimerActivity = null;
	
	//timer states
	TimerState mLastTimerState = TimerState.OFF;
	long mTimerNextRun = 0;							//in milliseconds, next time this should wake up
	
	@Override
	public void onCreate() {
		mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		mPM = (PowerManager) getSystemService(POWER_SERVICE);
		
		mHandler = new Handler();
		Log.i(LOG_TAG, "Service created");
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i(LOG_TAG, "Service started");
		//We want this service to continue running until it is explicitly stopped, so return sticky.
		return START_STICKY;
	}

	@Override
	public void onDestroy() {
		//clean up just in case
		stopTimer();
		Log.i(LOG_TAG, "Service destroyed");
	}

	@Override
	public IBinder onBind(Intent intent) {
		Log.i(LOG_TAG, "Service bounded");
		return mBinder;
	}

	@Override
	public boolean onUnbind(Intent intent) {
		mFlightTimerActivity = null;
		Log.i(LOG_TAG, "Service unbounded");
		return super.onUnbind(intent);
	}
	
	//used by main activity to set this reference
	void setActivity(FlightTimerActivity activity)
	{
		mFlightTimerActivity = activity;
	}
	
	//restart if currently running
	public void startTimer()
	{
		//reset states just in case
		stopTimer();

		mWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "RCFLocalTimerService");
		mWakeLock.acquire();
		
		//restart 
		updateNotification(TimerState.COUNTING_DOWN);
		mLastTimerState = TimerState.COUNTING_DOWN;
		long current_time = SystemClock.uptimeMillis();
		mTimerNextRun = current_time + 1000;
		mHandler.postAtTime(mTimerTask, mTimerNextRun);
	}
	
	public void stopTimer()
	{
		if (mWakeLock != null)
		{
			mWakeLock.release();
			mWakeLock = null;
		}
		updateNotification(TimerState.OFF);
		mHandler.removeCallbacks(mTimerTask);
		mLastTimerState = TimerState.OFF;
		mTimerNextRun = 0;
	}
	
	public void pauseTimer()
	{
		if (mLastTimerState == TimerState.COUNTING_DOWN)
		{
			updateNotification(TimerState.COUNTING_DOWN_PAUSED);
			mLastTimerState = TimerState.COUNTING_DOWN_PAUSED;
		}
		else if (mLastTimerState == TimerState.COUNTING_UP)
		{
			updateNotification(TimerState.COUNTING_UP_PAUSED);
			mLastTimerState = TimerState.COUNTING_UP_PAUSED;
		}
	}
	
	public void unpauseTimer()
	{
		if (mLastTimerState == TimerState.COUNTING_DOWN_PAUSED)
		{
			updateNotification(TimerState.COUNTING_DOWN);
			mLastTimerState = TimerState.COUNTING_DOWN;
		}
		else if (mLastTimerState == TimerState.COUNTING_UP_PAUSED)
		{
			updateNotification(TimerState.COUNTING_UP);
			mLastTimerState = TimerState.COUNTING_UP;
		}
	}
	
	private void updateNotification(TimerState state) {
		Notification notification;
		Intent notificationIntent;
		PendingIntent contentIntent;
	
		String ticker_text = "";
		String notification_title = "RC Flight Timer";
		String notification_text = "";
		int icon_id = R.drawable.notification_green;
		
		switch (state)
		{
		case OFF:
			mNM.cancel(LTS_NOTIFICATION);
			return;
		case COUNTING_DOWN:
			ticker_text = "Flight timer counting down";
			notification_text = "counting down ...";
			icon_id = R.drawable.notification_green;
			break;
		case COUNTING_UP:
			ticker_text = "Flight timer counting up";
			notification_text = "counting down ...";
			icon_id = R.drawable.notification_red;
			break;
		case COUNTING_DOWN_PAUSED:
			ticker_text = "Flight timer paused";
			notification_text = "paused ...";
			icon_id = R.drawable.notification_green;
			break;
		case COUNTING_UP_PAUSED:
			ticker_text = "Flight timer paused";
			notification_text = "paused ...";
			icon_id = R.drawable.notification_red;
			break;
		}
		
		notification = new Notification(icon_id, ticker_text, System.currentTimeMillis());
		notificationIntent = new Intent(getApplicationContext(), FlightTimerActivity.class);
		contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
		notification.flags |= Notification.FLAG_NO_CLEAR;
		notification.setLatestEventInfo(getApplicationContext(), notification_title, notification_text, contentIntent);
		// Send the notification.
		mNM.notify(LTS_NOTIFICATION, notification);
	}
	
	private Runnable mTimerTask = new Runnable() {
		public void run() {
			if (mFlightTimerActivity != null)
			{
				TimerState state = mFlightTimerActivity.timerTick();
				Log.i(LOG_TAG, "Tick = " + state); 
				if (state == TimerState.OFF)
				{
					stopTimer();
				}
				else
				{
					if (state != mLastTimerState)
					{
						updateNotification(state);
						mLastTimerState = state;
					}
					long current_time = SystemClock.uptimeMillis();
					mTimerNextRun += 1000;
					if (mTimerNextRun <= current_time)
						mTimerNextRun = current_time + 100; //something is screwed up, try best as we can
					
					mHandler.postAtTime(this, mTimerNextRun);
				}
			}

		}
	};

}
